﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SG.Domain;

namespace SG.Logic.Stock
{
    public abstract class Exponencial : ContextManager
    {

        protected  int DECIMALES = 4;
        protected double _prom;
        protected double _tendencia;
        protected double _indice;
        protected double _alpha;


        abstract public double GenerarPrediccion(Periodo perUltimo, int h);

        abstract public void ActualizarPeriodo(Periodo anterior, Periodo nuevo);

        public void CalcularErrores(Periodo anterior, Periodo nuevo)
        {
            Error error = nuevo.Error;

            _alpha = nuevo.Articulo.Alpha;
            /* 25/06
            error.ValorError = Aproximar(CalcularError(nuevo.Prediccion, nuevo.Demanda), DECIMALES);
            error.ErrorPromedio = Aproximar(CalcularErrorPromedio(error.ValorError, anterior.Error.ErrorPromedio), DECIMALES);
            error.MSEn = Aproximar(CalcularMSEn(error.ValorError, anterior.Error.MSEn), DECIMALES);
            error.DesviacionEstandar = Aproximar(CalcularDesviacionEst(error.MSEn), DECIMALES);
            error.SenialRastreo = Aproximar(CalcularSenialRastreo(error.ErrorPromedio, error.DesviacionEstandar), DECIMALES);
            Context.Periodo.AddObject(nuevo);
            Context.SaveChanges();
            */
            error.ValorError = CalcularError(nuevo.Prediccion, nuevo.Demanda);
            error.ErrorPromedio = CalcularErrorPromedio(error.ValorError, anterior.Error.ErrorPromedio);
            error.MSEn = CalcularMSEn(error.ValorError, anterior.Error.MSEn);
            error.DesviacionEstandar = CalcularDesviacionEst(error.MSEn);
            error.SenialRastreo = CalcularSenialRastreo(error.ErrorPromedio, error.DesviacionEstandar);
            if(nuevo.Id==0)
            Context.Periodo.AddObject(nuevo);
            Context.SaveChanges();
        }

        public double CalcularError(double predAnt, double demAct)
        {
            //return Math.Abs(predAnt - demAct);
            return predAnt - demAct;
        }

        public double CalcularErrorPromedio(double errAct, double errPromAnt)
        {
            return (_alpha * errAct + (1.0 - _alpha) * errPromAnt);
        }

        public double CalcularMSEn(double errAct, double mseAnt)
        {
            return (_alpha * Math.Pow(errAct, 2) + (1.0 - _alpha) * mseAnt);
        }

        abstract public double CalcularDesviacionEst(double mseAct);

        public double CalcularSenialRastreo(double errPromAct, double desvEstErrAct)
        {
            return (errPromAct / desvEstErrAct);
        }

        public double Aproximar(double valor, int decimales)
        {


            return new Random((int)(valor * Math.Pow(10, decimales))).Next() / Math.Pow(10, decimales);
        }

    }
}
